package org.catspaw.cherubim.persistence.jdbc.transaction;

import java.sql.Connection;
import java.sql.SQLException;

import org.catspaw.cherubim.persistence.TransactionException;
import org.catspaw.cherubim.persistence.TransactionManager;
import org.catspaw.cherubim.persistence.jdbc.ConnectionCallback;
import org.catspaw.cherubim.persistence.jdbc.ConnectionManager;
import org.catspaw.cherubim.persistence.jdbc.DefaultConnectionManager;

public final class TransactionUtils {

	private static ConnectionManager	connectionManager	= new DefaultConnectionManager();
	private static TransactionManager	transactionManager	= new JdbcTransactionManager(
																	connectionManager);

	public static Object doInTransaction(ConnectionCallback callback)
			throws TransactionException {
		Connection conn;
		try {
			conn = connectionManager.getCurrentConnection();
		} catch (SQLException e) {
			throw new TransactionException(e);
		}
		boolean binding = conn != null;
		if (!binding) {
			try {
				conn = connectionManager.getConnection();
			} catch (SQLException e) {
				throw new TransactionException(e);
			}
		}
		boolean in = transactionManager.inTransaction();
		try {
			if (!in) {
				transactionManager.beginTransaction();
			}
			Object o = callback.execute(conn);
			if (!in) {
				transactionManager.commit();
			}
			return o;
		} catch (RuntimeException e) {
			if (in) {
				transactionManager.rollback();
			}
			throw e;
		} catch (Error e) {
			if (in) {
				transactionManager.rollback();
			}
			throw e;
		} finally {
			if (!binding) {
				try {
					connectionManager.closeCurrentConnection();
				} catch (SQLException e) {
					throw new TransactionException(e);
				}
			}
		}
	}
}
